/**
 * 队列配置管理
 * EndoSight-UC 医疗AI系统
 *
 * Redis + Bull Queue 配置和管理
 * 支持医疗级优先级队列和HIPAA合规
 * 支持优雅降级 - 在Redis不可用时自动禁用队列功能
 */

import IORedis from 'ioredis';
import Bull from 'bull';
import winston from 'winston';
import crypto from 'crypto';

// 配置日志记录器
const logger = winston.createLogger({
  level: 'info',
  format: winston.format.combine(
    winston.format.timestamp(),
    winston.format.json()
  ),
  transports: [
    new winston.transports.Console({
      format: winston.format.simple()
    })
  ]
});

// 队列优先级定义 (医疗场景优先级)
export const QueuePriority = {
  CRITICAL: 10,      // 紧急医疗案例 - 立即处理
  URGENT: 8,         // 急诊案例 - 高优先级
  HIGH: 6,           // 重要医疗操作
  NORMAL: 4,         // 常规医疗处理
  LOW: 2,            // 后台维护任务
  CLEANUP: 1         // 数据清理任务
};

// 队列类型定义
export const QueueType = {
  CRITICAL: 'critical-medical',      // 紧急医疗队列
  AI_INFERENCE: 'ai-inference',      // AI推理队列
  FILE_PROCESSING: 'file-processing', // 文件处理队列
  CLEANUP: 'cleanup',                // 清理任务队列
  NOTIFICATION: 'notification',      // 通知队列
  REPORTING: 'reporting'             // 报告生成队列
};

// Redis连接配置
const REDIS_CONFIG = {
  host: process.env.REDIS_HOST || 'localhost',
  port: parseInt(process.env.REDIS_PORT) || 6379,
  password: process.env.REDIS_PASSWORD || undefined,
  db: parseInt(process.env.REDIS_DB) || 0,
  retryDelayOnFailover: 100,
  maxRetriesPerRequest: 3,
  lazyConnect: true,
  keepAlive: 30000,
  family: 4,
  // HIPAA合规 - 加密连接
  tls: process.env.NODE_ENV === 'production' ? {
    rejectUnauthorized: true,
    requestCert: true,
    agent: false
  } : false
};

// Bull队列默认配置
const BULL_QUEUE_CONFIG = {
  redis: REDIS_CONFIG,
  defaultJobOptions: {
    removeOnComplete: 50,      // 保留最近50个完成的任务
    removeOnFail: 100,         // 保留最近100个失败的任务
    attempts: 3,               // 默认重试次数
    backoff: {
      type: 'exponential',
      delay: 2000              // 指数退避延迟
    },
    // HIPAA合规 - 任务数据加密
    settings: {
      encrypt: process.env.NODE_ENV === 'production'
    }
  },
  settings: {
    stalledInterval: 30 * 1000,      // 30秒检查停滞任务
    maxStalledCount: 1,               // 最大停滞次数
    guardInterval: 5 * 1000,         // 5秒保护间隔
    retryProcessDelay: 5 * 1000,     // 5秒重试处理延迟
    drainDelay: 5                     // 5秒排空延迟
  }
};

/**
 * Redis连接管理器
 */
class RedisConnectionManager {
  constructor() {
    this.connections = new Map();
    this.mainConnection = null;
  }

  /**
   * 获取Redis连接
   */
  async getConnection(name = 'default') {
    if (this.connections.has(name)) {
      return this.connections.get(name);
    }

    const connection = new IORedis(REDIS_CONFIG);

    // 连接事件监听
    connection.on('connect', () => {
      logger.info(`Redis连接已建立: ${name}`, {
        connection: name,
        host: REDIS_CONFIG.host,
        port: REDIS_CONFIG.port
      });
    });

    connection.on('error', (error) => {
      logger.error(`Redis连接错误: ${name}`, {
        connection: name,
        error: error.message
      });
    });

    connection.on('close', () => {
      logger.warn(`Redis连接已关闭: ${name}`, { connection: name });
    });

    // 测试连接
    await connection.ping();

    this.connections.set(name, connection);

    if (name === 'default') {
      this.mainConnection = connection;
    }

    return connection;
  }

  /**
   * 关闭所有连接
   */
  async closeAll() {
    const closePromises = Array.from(this.connections.values()).map(conn => conn.quit());
    await Promise.all(closePromises);
    this.connections.clear();
    this.mainConnection = null;
  }

  /**
   * 获取连接状态
   */
  getStatus() {
    return {
      totalConnections: this.connections.size,
      connections: Array.from(this.connections.keys()),
      mainConnectionStatus: this.mainConnection?.status || 'disconnected'
    };
  }
}

/**
 * 队列管理器
 */
class QueueManager {
  constructor() {
    this.redisManager = new RedisConnectionManager();
    this.queues = new Map();
    this.isInitialized = false;
    this.redisAvailable = false;
  }

  /**
   * 初始化队列系统
   */
  async initialize() {
    try {
      logger.info('正在初始化队列系统...');

      // 尝试获取Redis连接
      let redis;
      try {
        redis = await this.redisManager.getConnection();
      } catch (redisError) {
        logger.warn('Redis连接失败，队列系统将以降级模式运行', {
          error: redisError.message,
          host: REDIS_CONFIG.host,
          port: REDIS_CONFIG.port
        });

        this.isInitialized = false;
        this.redisAvailable = false;
        return;
      }

      // 创建核心队列
      await this.createQueue(QueueType.CRITICAL, {
        ...BULL_QUEUE_CONFIG,
        defaultJobOptions: {
          ...BULL_QUEUE_CONFIG.defaultJobOptions,
          priority: QueuePriority.CRITICAL
        }
      });

      await this.createQueue(QueueType.AI_INFERENCE, {
        ...BULL_QUEUE_CONFIG,
        defaultJobOptions: {
          ...BULL_QUEUE_CONFIG.defaultJobOptions,
          priority: QueuePriority.NORMAL,
          // AI推理任务特殊配置
          delay: 0,
          attempts: 5,  // AI推理重试更多次
          backoff: {
            type: 'exponential',
            delay: 3000
          }
        },
        // AI推理队列配置
        settings: {
          ...BULL_QUEUE_CONFIG.settings,
          concurrency: 2  // 限制并发AI推理任务
        }
      });

      await this.createQueue(QueueType.FILE_PROCESSING, {
        ...BULL_QUEUE_CONFIG,
        defaultJobOptions: {
          ...BULL_QUEUE_CONFIG.defaultJobOptions,
          priority: QueuePriority.NORMAL,
          attempts: 2
        },
        settings: {
          ...BULL_QUEUE_CONFIG.settings,
          concurrency: 3  // 文件处理并发数
        }
      });

      await this.createQueue(QueueType.CLEANUP, {
        ...BULL_QUEUE_CONFIG,
        defaultJobOptions: {
          ...BULL_QUEUE_CONFIG.defaultJobOptions,
          priority: QueuePriority.CLEANUP,
          attempts: 1,
          removeOnComplete: 10
        },
        settings: {
          ...BULL_QUEUE_CONFIG.settings,
          concurrency: 1  // 清理任务单线程执行
        }
      });

      await this.createQueue(QueueType.NOTIFICATION, {
        ...BULL_QUEUE_CONFIG,
        defaultJobOptions: {
          ...BULL_QUEUE_CONFIG.defaultJobOptions,
          priority: QueuePriority.LOW,
          attempts: 3
        }
      });

      await this.createQueue(QueueType.REPORTING, {
        ...BULL_QUEUE_CONFIG,
        defaultJobOptions: {
          ...BULL_QUEUE_CONFIG.defaultJobOptions,
          priority: QueuePriority.LOW,
          attempts: 2
        }
      });

      this.isInitialized = true;
      this.redisAvailable = true;

      logger.info('✅ 队列系统初始化完成', {
        queueCount: this.queues.size,
        queues: Array.from(this.queues.keys()),
        redisAvailable: true
      });

      // 设置队列监控
      this.setupQueueMonitoring();

      return true;
    } catch (error) {
      logger.error('队列系统初始化失败:', error);
      throw error;
    }
  }

  /**
   * 创建队列
   */
  async createQueue(name, config = {}) {
    if (this.queues.has(name)) {
      return this.queues.get(name);
    }

    const queue = new Bull(name, config);

    // 队列事件监听
    queue.on('error', (error) => {
      logger.error(`队列错误: ${name}`, {
        queue: name,
        error: error.message
      });
    });

    queue.on('waiting', (jobId) => {
      logger.debug(`任务等待中: ${name}:${jobId}`, {
        queue: name,
        jobId
      });
    });

    queue.on('active', (job) => {
      logger.info(`任务开始处理: ${name}:${job.id}`, {
        queue: name,
        jobId: job.id,
        data: job.data.type || 'unknown'
      });
    });

    queue.on('completed', (job, result) => {
      logger.info(`任务完成: ${name}:${job.id}`, {
        queue: name,
        jobId: job.id,
        duration: Date.now() - job.timestamp,
        data: job.data.type || 'unknown'
      });
    });

    queue.on('failed', (job, error) => {
      logger.error(`任务失败: ${name}:${job.id}`, {
        queue: name,
        jobId: job.id,
        error: error.message,
        attempts: job.attemptsMade,
        data: job.data.type || 'unknown'
      });
    });

    queue.on('stalled', (job) => {
      logger.warn(`任务停滞: ${name}:${job.id}`, {
        queue: name,
        jobId: job.id
      });
    });

    this.queues.set(name, queue);
    return queue;
  }

  /**
   * 获取队列
   */
  getQueue(name) {
    return this.queues.get(name);
  }

  /**
   * 获取所有队列
   */
  getAllQueues() {
    return Array.from(this.queues.values());
  }

  /**
   * 添加任务到队列
   */
  async addJob(queueName, jobData, options = {}) {
    // 检查Redis是否可用
    if (!this.redisAvailable) {
      logger.warn('Redis不可用，跳过队列任务', {
        queueName,
        jobId: jobData.id || 'unknown',
        action: 'queue_disabled_fallback'
      });
      return {
        success: false,
        error: 'Redis不可用，队列功能已禁用',
        fallbackMode: true,
        queueName,
        jobId: jobData.id
      };
    }

    const queue = this.getQueue(queueName);
    if (!queue) {
      throw new Error(`队列不存在: ${queueName}`);
    }

    // 添加HIPAA合规字段
    const enhancedJobData = {
      ...jobData,
      id: crypto.randomUUID(),
      timestamp: new Date().toISOString(),
      correlationId: options.correlationId || crypto.randomUUID(),
      userId: options.userId || null,
      sessionId: options.sessionId || null,
      complianceFlags: {
        phiDetected: this.detectPHI(jobData),
        encryptionRequired: process.env.NODE_ENV === 'production',
        auditRequired: true
      }
    };

    // 添加医疗优先级逻辑
    let priority = options.priority || QueuePriority.NORMAL;
    if (jobData.isEmergency) {
      priority = QueuePriority.CRITICAL;
    } else if (jobData.isUrgent) {
      priority = QueuePriority.URGENT;
    }

    const jobOptions = {
      ...options,
      priority,
      // HIPAA合规 - 任务数据加密
      settings: {
        ...options.settings,
        encrypt: process.env.NODE_ENV === 'production'
      }
    };

    const job = await queue.add(enhancedJobData.type || 'default', enhancedJobData, jobOptions);

    logger.info(`任务已添加到队列: ${queueName}:${job.id}`, {
      queue: queueName,
      jobId: job.id,
      type: enhancedJobData.type,
      priority,
      userId: options.userId
    });

    return job;
  }

  /**
   * 获取队列状态
   */
  async getQueueStatus() {
    const status = {};

    for (const [name, queue] of this.queues) {
      const waiting = await queue.getWaiting();
      const active = await queue.getActive();
      const completed = await queue.getCompleted();
      const failed = await queue.getFailed();
      const delayed = await queue.getDelayed();

      status[name] = {
        waiting: waiting.length,
        active: active.length,
        completed: completed.length,
        failed: failed.length,
        delayed: delayed.length,
        total: waiting.length + active.length + completed.length + failed.length + delayed.length
      };
    }

    return {
      queues: status,
      redis: this.redisManager.getStatus(),
      isInitialized: this.isInitialized
    };
  }

  /**
   * 设置队列监控
   */
  setupQueueMonitoring() {
    // 定期收集队列指标
    setInterval(async () => {
      try {
        const status = await this.getQueueStatus();
        // 这里可以添加Prometheus指标导出
        logger.debug('队列状态监控', status);
      } catch (error) {
        logger.error('队列监控错误:', error);
      }
    }, 30000); // 每30秒监控一次
  }

  /**
   * 检测PHI数据
   */
  detectPHI(data) {
    const phiPatterns = [
      /\b(patient|mrn|medical\s*record)\s*#?\s*[\w-]+/gi,
      /\b\d{3}-\d{2}-\d{4}\b/g,  // SSN
      /\b\d{3}[-.]?\d{3}[-.]?\d{4}\b/g,  // Phone
      /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g  // Email
    ];

    const dataString = JSON.stringify(data);
    return phiPatterns.some(pattern => pattern.test(dataString));
  }

  /**
   * 关闭队列系统
   */
  async close() {
    logger.info('正在关闭队列系统...');

    const closePromises = Array.from(this.queues.values()).map(queue => queue.close());
    await Promise.all(closePromises);

    await this.redisManager.closeAll();
    this.queues.clear();
    this.isInitialized = false;

    logger.info('✅ 队列系统已关闭');
  }

  /**
   * 清理队列
   */
  async cleanQueues() {
    logger.info('正在清理队列...');

    for (const [name, queue] of this.queues) {
      await queue.clean(0, 'completed');
      await queue.clean(0, 'failed');
      logger.info(`队列已清理: ${name}`);
    }
  }
}

// 创建全局队列管理器实例
const queueManager = new QueueManager();

export default queueManager;

// 导出配置常量
export { REDIS_CONFIG, BULL_QUEUE_CONFIG };